#include "hook.h"

BOOL InitializeHook()
{
	HOOKRESULT result;
	if ((result = InitializeHook(MouseHookProc)) != HookResultCodes::OK)
	{
		WriteErrorLogEntry(L"InitializeHook", result);
		return FALSE;
	}
	if ((result = StartHook(0, NULL)) != HookResultCodes::OK)
	{
		WriteErrorLogEntry(L"InitializeHook", result);
		return FALSE;
	}
	return TRUE;
}

BOOL ShutdownHook()
{
	HOOKRESULT result;
	if ((result = StopHook()) != HookResultCodes::OK)
	{
		WriteErrorLogEntry(L"StopHook", result);
		return FALSE;
	}
	if ((result = UninitializeHook()) != HookResultCodes::OK)
	{
		WriteErrorLogEntry(L"UninitializeHook", result);
		return FALSE;
	}
	return TRUE;
}

BOOL CALLBACK MouseHookProc(int code, WPARAM w, LPARAM l, void* userData)
{
	static POINT p;
	static HWND hWnd;
	static MSLLHOOKSTRUCT *info;
	static wchar_t name[256];

	if (_disableScrollPP)
		return TRUE;

	if (code < 0 || w != WM_MOUSEWHEEL)
		return TRUE;
	info = (MSLLHOOKSTRUCT*)l;

	if (!GetCursorPos(&p))
		return TRUE;

	if ((hWnd = GetWindowAtPosition(info->pt.x, info->pt.y)) == NULL)
		return TRUE;

	if (!GetClassName(hWnd, name, 256))
		return TRUE;

	if (!wcscmp(name, TOOLTIPS_CLASS))
	{
		HWND tmp = hWnd;
		ShowWindow(tmp, SW_HIDE);
		hWnd = GetWindowAtPosition(info->pt.x, info->pt.y);
		ShowWindow(tmp, SW_SHOW);
		if (!hWnd)
			return TRUE;

		if (!GetClassName(hWnd, name, 256))
			return TRUE;
	}

	if (!wcscmp(name, STOREAPP_CLASSNAME)) //ignore Windows Store apps
		return TRUE;

	LONG style = GetWindowLong(hWnd, GWL_STYLE);
	if (!wcscmp(name, L"Button") && (style & BS_GROUPBOX))
	{
		HWND tmp = hWnd;
		EnableWindow(tmp, FALSE);
		hWnd = GetWindowAtPosition(info->pt.x, info->pt.y);
		EnableWindow(tmp, TRUE);
		if (!hWnd)
			hWnd = tmp;
	}

	WORD keys = 0;

	if ((GetKeyState(VK_CONTROL) | GetKeyState(VK_LCONTROL) | GetKeyState(VK_RCONTROL)) & SHIFTED)
		keys |= MK_CONTROL;
	if ((GetKeyState(VK_SHIFT) | GetKeyState(VK_LSHIFT) | GetKeyState(VK_RSHIFT)) & SHIFTED)
		keys |= MK_SHIFT;
	if (GetKeyState(VK_LBUTTON) & SHIFTED)
		keys |= MK_LBUTTON;
	if (GetKeyState(VK_RBUTTON) & SHIFTED)
		keys |= MK_RBUTTON;
	if (GetKeyState(VK_MBUTTON) & SHIFTED)
		keys |= MK_MBUTTON;
	if (GetKeyState(VK_XBUTTON1) & SHIFTED)
		keys |= MK_XBUTTON1;
	if (GetKeyState(VK_XBUTTON2) & SHIFTED)
		keys |= MK_XBUTTON2;

	//TODO: Add support for scrolling directly lines instead of sending MouseWheel messages.
	if (!PostMessage(hWnd, WM_MOUSEWHEEL, //Post the message
		info->mouseData & 0xFFFF0000 | keys,
		MAKELPARAM(info->pt.x, info->pt.y)))
	{
		return TRUE;
	}

	return FALSE;
}

HWND GetWindowAtPosition(int x, int y)
{
	POINT pt;
	pt.x = x;
	pt.y = y;
	return WindowFromPoint(pt);
}